package com.xmut.xmutbackend.service;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.xmut.xmutbackend.entity.AIResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;
import reactor.util.retry.Retry;

import java.time.Duration;
import java.util.Map;

@Service
public class AIService {

    private static final Logger logger = LoggerFactory.getLogger(AIService.class);

    private final WebClient webClient;
    private final String botId;
    private final ObjectMapper objectMapper;

    public static class AIException extends RuntimeException {
        private final int statusCode;
        public AIException(String message, int statusCode) {
            super(message);
            this.statusCode = statusCode;
        }
        public int getStatusCode() {
            return statusCode;
        }
    }

    public AIService(WebClient cozeWebClient,
                     @Value("${coze.bot-id}") String botId,
                     ObjectMapper objectMapper) {
        this.webClient = cozeWebClient;
        this.botId = botId;
        this.objectMapper = objectMapper;
    }

    public Mono<AIResponse> chat(String message, String conversationId) {
        Map<String, Object> payload = createRequestPayload(message, conversationId);
        return webClient.post()
                .bodyValue(payload)
                .retrieve()
                .onStatus(
                        status -> status.value() >= 400,
                        response -> response.bodyToMono(String.class)
                                .flatMap(errorBody -> Mono.error(new AIException(
                                        "AI服务返回错误: " + errorBody,
                                        response.statusCode().value()
                                )))
                )
                .bodyToMono(String.class)
                .timeout(Duration.ofSeconds(30))
                .retryWhen(Retry.backoff(3, Duration.ofSeconds(2)))
                .flatMap(this::parseResponse)
                .doOnSubscribe(sub -> logger.info("开始处理问题: {}", message))
                .doOnSuccess(res -> logger.info("处理成功: {}", res.getAnswer()))
                .doOnError(e -> logger.error("AI处理失败", e));
    }

    private Map<String, Object> createRequestPayload(String message, String conversationId) {
        if (conversationId == null || conversationId.isEmpty()) {
            return Map.of(
                    "bot_id", botId,
                    "user", "spring_client",
                    "query", message,
                    "temperature", 0.7,
                    "max_tokens", 2000
            );
        } else {
            return Map.of(
                    "bot_id", botId,
                    "user", "spring_client",
                    "query", message,
                    "temperature", 0.7,
                    "max_tokens", 2000,
                    "conversation_id", conversationId
            );
        }
    }

    private Mono<AIResponse> parseResponse(String json) {
        return Mono.fromCallable(() -> {
            JsonNode root = objectMapper.readTree(json);
            if (root.path("code").asInt() != 0) {
                throw new AIException(root.path("msg").asText("AI响应失败"), root.path("code").asInt());
            }

            AIResponse response = new AIResponse();
            for (JsonNode msg : root.path("messages")) {
                if ("answer".equals(msg.path("type").asText())) {
                    response.setAnswer(msg.path("content").asText());
                    response.setConversationId(root.path("conversation_id").asText());
                    response.setSuccess(true);
                    return response;
                }
            }

            throw new AIException("未找到 AI 回答内容", 404);
        });
    }
}
